From 0491c8a6d26d25392b3b2458bea2b006bea88c7d Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 29 Mar 2007 15:14:26 +0100 Subject: [PATCH] xen: Split domain_flags into discrete first-class fields in the domain structure. This makes them quicker to access, and simplifies domain pause and checking of runnable status. Signed-off-by: Keir Fraser --- xen/arch/ia64/xen/mm.c | 5 ++- xen/arch/powerpc/mm.c | 10 +++--- xen/arch/x86/domain.c | 4 +-- xen/arch/x86/domain_build.c | 2 +- xen/arch/x86/mm.c | 12 ++++--- xen/arch/x86/mm/hap/hap.c | 2 +- xen/arch/x86/mm/shadow/common.c | 4 +-- xen/arch/x86/mm/shadow/multi.c | 4 +-- xen/arch/x86/x86_64/asm-offsets.c | 3 +- xen/arch/x86/x86_64/entry.S | 26 +++++--------- xen/common/domain.c | 57 ++++++++++++------------------- xen/common/domctl.c | 8 ++--- xen/common/event_channel.c | 3 +- xen/common/grant_table.c | 16 ++++----- xen/common/keyhandler.c | 4 +-- xen/common/memory.c | 2 +- xen/common/page_alloc.c | 4 +-- xen/common/schedule.c | 4 ++- xen/include/xen/sched.h | 48 ++++++++------------------ xen/include/xen/spinlock.h | 7 ++++ 20 files changed, 95 insertions(+), 130 deletions(-) diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index e055757cc2..6cd28d3457 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -400,7 +400,7 @@ share_xen_page_with_guest(struct page_info *page, ASSERT(page->count_info == 0); /* Only add to the allocation list if the domain isn't dying. */ - if ( !test_bit(_DOMF_dying, &d->domain_flags) ) + if ( !d->is_dying ) { page->count_info |= PGC_allocated | 1; if ( unlikely(d->xenheap_pages++ == 0) ) @@ -1935,8 +1935,7 @@ void put_page_type(struct page_info *page) * page-table pages if we detect a referential loop. * See domain.c:relinquish_list(). */ - ASSERT((x & PGT_validated) || - test_bit(_DOMF_dying, &page_get_owner(page)->domain_flags)); + ASSERT((x & PGT_validated) || page_get_owner(page)->is_dying); if ( unlikely((nx & PGT_count_mask) == 0) ) { diff --git a/xen/arch/powerpc/mm.c b/xen/arch/powerpc/mm.c index d48ce3a7f5..2dec97ad1b 100644 --- a/xen/arch/powerpc/mm.c +++ b/xen/arch/powerpc/mm.c @@ -106,7 +106,7 @@ void share_xen_page_with_guest( ASSERT(page->count_info == 0); /* Only add to the allocation list if the domain isn't dying. */ - if ( !test_bit(_DOMF_dying, &d->domain_flags) ) + if ( !d->is_dying ) { page->count_info |= PGC_allocated | 1; if ( unlikely(d->xenheap_pages++ == 0) ) @@ -218,8 +218,7 @@ void put_page_type(struct page_info *page) * page-table pages if we detect a referential loop. * See domain.c:relinquish_list(). */ - ASSERT((x & PGT_validated) || - test_bit(_DOMF_dying, &page_get_owner(page)->domain_flags)); + ASSERT((x & PGT_validated) || page_get_owner(page)->is_dying); if ( unlikely((nx & PGT_count_mask) == 0) ) { @@ -402,7 +401,7 @@ int allocate_rma(struct domain *d, unsigned int order) void free_rma_check(struct page_info *page) { if (test_bit(_PGC_page_RMA, &page->count_info)) { - if (!test_bit(_DOMF_dying, &page_get_owner(page)->domain_flags)) { + if (!page_get_owner(page)->is_dying) { panic("Attempt to free an RMA page: 0x%lx\n", page_to_mfn(page)); } else { clear_bit(_PGC_page_RMA, &page->count_info); @@ -439,8 +438,7 @@ ulong pfn2mfn(struct domain *d, ulong pfn, int *type) mfn = d->arch.p2m[pfn]; } #ifdef DEBUG - if (t != PFN_TYPE_NONE && - (d->domain_flags & DOMF_dying) && + if (t != PFN_TYPE_NONE && d->is_dying && page_get_owner(mfn_to_page(mfn)) != d) { printk("%s: page type: %d owner Dom[%d]:%p expected Dom[%d]:%p\n", __func__, t, diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 6a543a3a1b..005813306c 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -274,7 +274,7 @@ int switch_native(struct domain *d) if ( !IS_COMPAT(d) ) return 0; - clear_bit(_DOMF_compat, &d->domain_flags); + d->is_compat = 0; release_arg_xlat_area(d); /* switch gdt */ @@ -306,7 +306,7 @@ int switch_compat(struct domain *d) if ( IS_COMPAT(d) ) return 0; - set_bit(_DOMF_compat, &d->domain_flags); + d->is_compat = 1; /* switch gdt */ gdt_l1e = l1e_from_page(virt_to_page(compat_gdt_table), PAGE_HYPERVISOR); diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 96215da601..a05060ee5e 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -324,7 +324,7 @@ int construct_dom0(struct domain *d, { l1_pgentry_t gdt_l1e; - set_bit(_DOMF_compat, &d->domain_flags); + d->is_compat = 1; v->vcpu_info = (void *)&d->shared_info->compat.vcpu_info[0]; if ( nr_pages != (unsigned int)nr_pages ) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 5bd5ef720f..d6ca78726a 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -271,7 +271,7 @@ void share_xen_page_with_guest( ASSERT(page->count_info == 0); /* Only add to the allocation list if the domain isn't dying. */ - if ( !test_bit(_DOMF_dying, &d->domain_flags) ) + if ( !d->is_dying ) { page->count_info |= PGC_allocated | 1; if ( unlikely(d->xenheap_pages++ == 0) ) @@ -806,8 +806,7 @@ void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d) * (Note that the undestroyable active grants are not a security hole in * Xen. All active grants can safely be cleaned up when the domain dies.) */ - if ( (l1e_get_flags(l1e) & _PAGE_GNTTAB) && - !(d->domain_flags & (DOMF_shutdown|DOMF_dying)) ) + if ( (l1e_get_flags(l1e) & _PAGE_GNTTAB) && !d->is_shutdown && !d->is_dying ) { MEM_LOG("Attempt to implicitly unmap a granted PTE %" PRIpte, l1e_get_intpte(l1e)); @@ -2054,9 +2053,12 @@ int do_mmuext_op( /* A page is dirtied when its pin status is set. */ mark_dirty(d, mfn); - /* We can race domain destruction (domain_relinquish_resources). */ + /* + * We can race domain destruction (domain_relinquish_resources). + * NB. The dying-flag test must happen /after/ setting PGT_pinned. + */ if ( unlikely(this_cpu(percpu_mm_info).foreign != NULL) && - test_bit(_DOMF_dying, &FOREIGNDOM->domain_flags) && + this_cpu(percpu_mm_info).foreign->is_dying && test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) put_page_and_type(page); diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c index f879c083c0..47139f2627 100644 --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -451,7 +451,7 @@ void hap_teardown(struct domain *d) mfn_t mfn; HERE_I_AM; - ASSERT(test_bit(_DOMF_dying, &d->domain_flags)); + ASSERT(d->is_dying); ASSERT(d != current->domain); if ( !hap_locked_by_me(d) ) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index ad4559aa24..8ef8b55b02 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -2461,7 +2461,7 @@ void shadow_teardown(struct domain *d) struct list_head *entry, *n; struct page_info *pg; - ASSERT(test_bit(_DOMF_dying, &d->domain_flags)); + ASSERT(d->is_dying); ASSERT(d != current->domain); if ( !shadow_locked_by_me(d) ) @@ -2992,7 +2992,7 @@ int shadow_domctl(struct domain *d, return -EINVAL; } - if ( unlikely(test_bit(_DOMF_dying, &d->domain_flags)) ) + if ( unlikely(d->is_dying) ) { gdprintk(XENLOG_INFO, "Ignoring shadow op on dying domain %u\n", d->domain_id); diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 774d7408f8..7945913429 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -2821,9 +2821,9 @@ static int sh_page_fault(struct vcpu *v, { /* Couldn't get the sl1e! Since we know the guest entries * are OK, this can only have been caused by a failed - * shadow_set_l*e(), which will have crashed the guest. + * shadow_set_l*e(), which will have crashed the guest. * Get out of the fault handler immediately. */ - ASSERT(test_bit(_DOMF_dying, &d->domain_flags)); + ASSERT(d->is_shutdown); unmap_walk(v, &gw); shadow_unlock(d); return 0; diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c index 053aee310e..4e4b103655 100644 --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -92,8 +92,7 @@ void __dummy__(void) OFFSET(VCPU_vmx_cr2, struct vcpu, arch.hvm_vmx.cpu_cr2); BLANK(); - OFFSET(DOMAIN_domain_flags, struct domain, domain_flags); - DEFINE(_DOMF_compat, _DOMF_compat); + OFFSET(DOMAIN_is_compat, struct domain, is_compat); BLANK(); OFFSET(VMCB_rax, struct vmcb_struct, rax); diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index f89c89109c..a69ac53de2 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -234,8 +234,8 @@ ENTRY(int80_direct_trap) jz int80_slow_path movq VCPU_domain(%rbx),%rax - btl $_DOMF_compat,DOMAIN_domain_flags(%rax) - jc compat_int80_direct_trap + testb $1,DOMAIN_is_compat(%rax) + jnz compat_int80_direct_trap call create_bounce_frame jmp restore_all_guest @@ -353,16 +353,12 @@ ENTRY(domain_crash_synchronous) GET_GUEST_REGS(%rax) movq %rax,%rsp # create_bounce_frame() temporarily clobbers CS.RPL. Fix up. -#ifdef CONFIG_COMPAT movq CPUINFO_current_vcpu(%rax),%rax movq VCPU_domain(%rax),%rax - btl $_DOMF_compat,DOMAIN_domain_flags(%rax) - setnc %al + testb $1,DOMAIN_is_compat(%rax) + setz %al leal (%rax,%rax,2),%eax orb %al,UREGS_cs(%rsp) -#else - orb $3,UREGS_cs(%rsp) -#endif # printk(domain_crash_synchronous_string) leaq domain_crash_synchronous_string(%rip),%rdi xorl %eax,%eax @@ -375,14 +371,10 @@ ENTRY(ret_from_intr) GET_CURRENT(%rbx) testb $3,UREGS_cs(%rsp) jz restore_all_xen -#ifndef CONFIG_COMPAT - jmp test_all_events -#else movq VCPU_domain(%rbx),%rax - btl $_DOMF_compat,DOMAIN_domain_flags(%rax) - jnc test_all_events + testb $1,DOMAIN_is_compat(%rax) + jz test_all_events jmp compat_test_all_events -#endif ALIGN /* No special register assumptions. */ @@ -401,11 +393,9 @@ handle_exception_saved: testb $3,UREGS_cs(%rsp) jz restore_all_xen leaq VCPU_trap_bounce(%rbx),%rdx -#ifdef CONFIG_COMPAT movq VCPU_domain(%rbx),%rax - btl $_DOMF_compat,DOMAIN_domain_flags(%rax) - jc compat_post_handle_exception -#endif + testb $1,DOMAIN_is_compat(%rax) + jnz compat_post_handle_exception testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx) jz test_all_events call create_bounce_frame diff --git a/xen/common/domain.c b/xen/common/domain.c index 53ba781882..f9e43a04ce 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -59,7 +59,6 @@ struct domain *alloc_domain(domid_t domid) atomic_set(&d->refcnt, 1); spin_lock_init(&d->big_lock); spin_lock_init(&d->page_alloc_lock); - spin_lock_init(&d->pause_lock); INIT_LIST_HEAD(&d->page_list); INIT_LIST_HEAD(&d->xenpage_list); @@ -161,9 +160,12 @@ struct domain *domain_create(domid_t domid, unsigned int domcr_flags) if ( !is_idle_domain(d) ) { - set_bit(_DOMF_ctrl_pause, &d->domain_flags); + d->is_paused_by_controller = 1; + atomic_inc(&d->pause_count); + if ( evtchn_init(d) != 0 ) goto fail1; + if ( grant_table_create(d) != 0 ) goto fail2; } @@ -262,9 +264,13 @@ void domain_kill(struct domain *d) { domain_pause(d); - if ( test_and_set_bit(_DOMF_dying, &d->domain_flags) ) + /* Already dying? Then bail. */ + if ( xchg(&d->is_dying, 1) ) return; + /* Tear down state /after/ setting the dying flag. */ + smp_wmb(); + gnttab_release_mappings(d); domain_relinquish_resources(d); put_domain(d); @@ -278,7 +284,7 @@ void domain_kill(struct domain *d) void __domain_crash(struct domain *d) { - if ( test_bit(_DOMF_shutdown, &d->domain_flags) ) + if ( d->is_shutdown ) { /* Print nothing: the domain is already shutting down. */ } @@ -327,7 +333,7 @@ void domain_shutdown(struct domain *d, u8 reason) if ( d->domain_id == 0 ) dom0_shutdown(reason); - if ( !test_and_set_bit(_DOMF_shutdown, &d->domain_flags) ) + if ( !xchg(&d->is_shutdown, 1) ) d->shutdown_code = reason; for_each_vcpu ( d, v ) @@ -341,7 +347,9 @@ void domain_pause_for_debugger(void) struct domain *d = current->domain; struct vcpu *v; - set_bit(_DOMF_ctrl_pause, &d->domain_flags); + atomic_inc(&d->pause_count); + if ( xchg(&d->is_paused_by_controller, 1) ) + domain_unpause(d); /* race-free atomic_dec(&d->pause_count) */ for_each_vcpu ( d, v ) vcpu_sleep_nosync(v); @@ -374,7 +382,7 @@ void domain_destroy(struct domain *d) struct domain **pd; atomic_t old, new; - BUG_ON(!test_bit(_DOMF_dying, &d->domain_flags)); + BUG_ON(!d->is_dying); /* May be already destroyed, or get_domain() can race us. */ _atomic_set(old, 0); @@ -442,10 +450,7 @@ void domain_pause(struct domain *d) ASSERT(d != current->domain); - spin_lock(&d->pause_lock); - if ( d->pause_count++ == 0 ) - set_bit(_DOMF_paused, &d->domain_flags); - spin_unlock(&d->pause_lock); + atomic_inc(&d->pause_count); for_each_vcpu( d, v ) vcpu_sleep_sync(v); @@ -454,43 +459,25 @@ void domain_pause(struct domain *d) void domain_unpause(struct domain *d) { struct vcpu *v; - int wake; ASSERT(d != current->domain); - spin_lock(&d->pause_lock); - wake = (--d->pause_count == 0); - if ( wake ) - clear_bit(_DOMF_paused, &d->domain_flags); - spin_unlock(&d->pause_lock); - - if ( wake ) + if ( atomic_dec_and_test(&d->pause_count) ) for_each_vcpu( d, v ) vcpu_wake(v); } void domain_pause_by_systemcontroller(struct domain *d) { - struct vcpu *v; - - BUG_ON(current->domain == d); - - if ( !test_and_set_bit(_DOMF_ctrl_pause, &d->domain_flags) ) - { - for_each_vcpu ( d, v ) - vcpu_sleep_sync(v); - } + domain_pause(d); + if ( xchg(&d->is_paused_by_controller, 1) ) + domain_unpause(d); } void domain_unpause_by_systemcontroller(struct domain *d) { - struct vcpu *v; - - if ( test_and_clear_bit(_DOMF_ctrl_pause, &d->domain_flags) ) - { - for_each_vcpu ( d, v ) - vcpu_wake(v); - } + if ( xchg(&d->is_paused_by_controller, 0) ) + domain_unpause(d); } int boot_vcpu(struct domain *d, int vcpuid, vcpu_guest_context_u ctxt) diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 952c419f1d..0f0c5998da 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -114,9 +114,9 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info) info->cpu_time = cpu_time; info->flags = flags | - ((d->domain_flags & DOMF_dying) ? XEN_DOMINF_dying : 0) | - ((d->domain_flags & DOMF_shutdown) ? XEN_DOMINF_shutdown : 0) | - ((d->domain_flags & DOMF_ctrl_pause) ? XEN_DOMINF_paused : 0) | + (d->is_dying ? XEN_DOMINF_dying : 0) | + (d->is_shutdown ? XEN_DOMINF_shutdown : 0) | + (d->is_paused_by_controller ? XEN_DOMINF_paused : 0) | d->shutdown_code << XEN_DOMINF_shutdownshift; if ( is_hvm_domain(d) ) @@ -288,7 +288,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) if ( d != NULL ) { ret = 0; - if ( test_and_clear_bit(_DOMF_shutdown, &d->domain_flags) ) + if ( xchg(&d->is_shutdown, 0) ) for_each_vcpu ( d, v ) vcpu_wake(v); rcu_unlock_domain(d); diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 6054527286..783dfb99f1 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -529,8 +529,7 @@ void evtchn_set_pending(struct vcpu *v, int port) } /* Check if some VCPU might be polling for this event. */ - if ( unlikely(test_bit(_DOMF_polling, &d->domain_flags)) && - likely(test_and_clear_bit(_DOMF_polling, &d->domain_flags)) ) + if ( unlikely(d->is_polling) && likely(xchg(&d->is_polling, 0)) ) { for_each_vcpu ( d, v ) if ( test_and_clear_bit(_VCPUF_polling, &v->vcpu_flags) ) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 2ea6ff37eb..da6b743c34 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -311,7 +311,7 @@ __gnttab_map_grant_ref( get_page_and_type(mfn_to_page(frame), rd, PGT_writable_page))) ) { - if ( !test_bit(_DOMF_dying, &rd->domain_flags) ) + if ( !rd->is_dying ) gdprintk(XENLOG_WARNING, "Could not pin grant frame %lx\n", frame); rc = GNTST_general_error; goto undo_out; @@ -865,16 +865,16 @@ gnttab_transfer( * headroom. Also, a domain mustn't have PGC_allocated * pages when it is dying. */ - if ( unlikely(test_bit(_DOMF_dying, &e->domain_flags)) || + if ( unlikely(e->is_dying) || unlikely(e->tot_pages >= e->max_pages) || unlikely(!gnttab_prepare_for_transfer(e, d, gop.ref)) ) { - if ( !test_bit(_DOMF_dying, &e->domain_flags) ) + if ( !e->is_dying ) gdprintk(XENLOG_INFO, "gnttab_transfer: " "Transferee has no reservation " "headroom (%d,%d) or provided a bad grant ref (%08x) " - "or is dying (%lx)\n", - e->tot_pages, e->max_pages, gop.ref, e->domain_flags); + "or is dying (%d)\n", + e->tot_pages, e->max_pages, gop.ref, e->is_dying); spin_unlock(&e->page_alloc_lock); rcu_unlock_domain(e); page->count_info &= ~(PGC_count_mask|PGC_allocated); @@ -1094,7 +1094,7 @@ __gnttab_copy( "source frame %lx invalid.\n", s_frame); if ( !get_page(mfn_to_page(s_frame), sd) ) { - if ( !test_bit(_DOMF_dying, &sd->domain_flags) ) + if ( !sd->is_dying ) gdprintk(XENLOG_WARNING, "Could not get src frame %lx\n", s_frame); rc = GNTST_general_error; goto error_out; @@ -1117,7 +1117,7 @@ __gnttab_copy( "destination frame %lx invalid.\n", d_frame); if ( !get_page_and_type(mfn_to_page(d_frame), dd, PGT_writable_page) ) { - if ( !test_bit(_DOMF_dying, &dd->domain_flags) ) + if ( !dd->is_dying ) gdprintk(XENLOG_WARNING, "Could not get dst frame %lx\n", d_frame); rc = GNTST_general_error; goto error_out; @@ -1352,7 +1352,7 @@ gnttab_release_mappings( struct active_grant_entry *act; struct grant_entry *sha; - BUG_ON(!test_bit(_DOMF_dying, &d->domain_flags)); + BUG_ON(!d->is_dying); for ( handle = 0; handle < gt->maptrack_limit; handle++ ) { diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index 471642aec6..e3eb0b9cee 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -164,9 +164,9 @@ static void dump_domains(unsigned char key) { printk("General information for domain %u:\n", d->domain_id); cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask); - printk(" flags=%lx refcnt=%d nr_pages=%d xenheap_pages=%d " + printk(" refcnt=%d nr_pages=%d xenheap_pages=%d " "dirty_cpus=%s\n", - d->domain_flags, atomic_read(&d->refcnt), + atomic_read(&d->refcnt), d->tot_pages, d->xenheap_pages, tmpstr); printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n", diff --git a/xen/common/memory.c b/xen/common/memory.c index 26a2fde5eb..5adef9b07c 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -345,7 +345,7 @@ static long memory_exchange(XEN_GUEST_HANDLE(xen_memory_exchange_t) arg) /* * Only support exchange on calling domain right now. Otherwise there are - * tricky corner cases to consider (e.g., DOMF_dying domain). + * tricky corner cases to consider (e.g., dying domain). */ if ( unlikely(exch.in.domid != DOMID_SELF) ) { diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index 913c6c9986..b6e0afb174 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -739,7 +739,7 @@ int assign_pages( spin_lock(&d->page_alloc_lock); - if ( unlikely(test_bit(_DOMF_dying, &d->domain_flags)) ) + if ( unlikely(d->is_dying) ) { gdprintk(XENLOG_INFO, "Cannot assign page to domain%d -- dying.\n", d->domain_id); @@ -869,7 +869,7 @@ void free_domheap_pages(struct page_info *pg, unsigned int order) spin_unlock_recursive(&d->page_alloc_lock); - if ( likely(!test_bit(_DOMF_dying, &d->domain_flags)) ) + if ( likely(!d->is_dying) ) { free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, order); } diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 560fadf504..6fc968126e 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -313,7 +313,9 @@ static long do_poll(struct sched_poll *sched_poll) /* These operations must occur in order. */ set_bit(_VCPUF_blocked, &v->vcpu_flags); set_bit(_VCPUF_polling, &v->vcpu_flags); - set_bit(_DOMF_polling, &d->domain_flags); + smp_wmb(); + d->is_polling = 1; + smp_wmb(); /* Check for events /after/ setting flags: avoids wakeup waiting race. */ for ( i = 0; i < sched_poll->nr_ports; i++ ) diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index dc68f32ead..2a86f77806 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -138,7 +138,6 @@ struct domain unsigned int xenheap_pages; /* # pages allocated from Xen heap */ /* Scheduling. */ - int shutdown_code; /* code value from OS (if DOMF_shutdown) */ void *sched_priv; /* scheduler-specific data */ struct domain *next_in_list; @@ -165,17 +164,26 @@ struct domain struct rangeset *iomem_caps; struct rangeset *irq_caps; - unsigned long domain_flags; - /* Is this an HVM guest? */ bool_t is_hvm; /* Is this guest fully privileged (aka dom0)? */ bool_t is_privileged; /* Is this guest being debugged by dom0? */ bool_t debugger_attached; + /* Is a 'compatibility mode' guest (semantics are arch specific)? */ + bool_t is_compat; + /* Are any VCPUs polling event channels (SCHEDOP_poll)? */ + bool_t is_polling; + /* Is this guest dying (i.e., a zombie)? */ + bool_t is_dying; + /* Domain is paused by controller software? */ + bool_t is_paused_by_controller; - spinlock_t pause_lock; - unsigned int pause_count; + /* Guest has shut down (inc. reason code)? */ + bool_t is_shutdown; + int shutdown_code; + + atomic_t pause_count; unsigned long vm_assist; @@ -452,28 +460,6 @@ extern struct domain *domain_list; #define _VCPUF_migrating 13 #define VCPUF_migrating (1UL<<_VCPUF_migrating) -/* - * Per-domain flags (domain_flags). - */ - /* Guest shut itself down for some reason. */ -#define _DOMF_shutdown 0 -#define DOMF_shutdown (1UL<<_DOMF_shutdown) - /* Death rattle. */ -#define _DOMF_dying 1 -#define DOMF_dying (1UL<<_DOMF_dying) - /* Domain is paused by controller software. */ -#define _DOMF_ctrl_pause 2 -#define DOMF_ctrl_pause (1UL<<_DOMF_ctrl_pause) - /* Are any VCPUs polling event channels (SCHEDOP_poll)? */ -#define _DOMF_polling 3 -#define DOMF_polling (1UL<<_DOMF_polling) - /* Domain is paused by the hypervisor? */ -#define _DOMF_paused 4 -#define DOMF_paused (1UL<<_DOMF_paused) - /* Domain is a compatibility one? */ -#define _DOMF_compat 5 -#define DOMF_compat (1UL<<_DOMF_compat) - static inline int vcpu_runnable(struct vcpu *v) { return ( !(v->vcpu_flags & @@ -482,10 +468,7 @@ static inline int vcpu_runnable(struct vcpu *v) VCPUF_paused | VCPUF_blocked_in_xen | VCPUF_migrating )) && - !(v->domain->domain_flags & - ( DOMF_shutdown | - DOMF_ctrl_pause | - DOMF_paused ))); + (atomic_read(&v->domain->pause_count) == 0) ); } void vcpu_pause(struct vcpu *v); @@ -511,8 +494,7 @@ static inline void vcpu_unblock(struct vcpu *v) #define IS_PRIV(_d) ((_d)->is_privileged) #ifdef CONFIG_COMPAT -#define IS_COMPAT(_d) \ - (test_bit(_DOMF_compat, &(_d)->domain_flags)) +#define IS_COMPAT(_d) ((_d)->is_compat) #else #define IS_COMPAT(_d) 0 #endif diff --git a/xen/include/xen/spinlock.h b/xen/include/xen/spinlock.h index 11f83119d4..fa8c82f8ea 100644 --- a/xen/include/xen/spinlock.h +++ b/xen/include/xen/spinlock.h @@ -82,6 +82,13 @@ typedef struct { int gcc_is_buggy; } rwlock_t; #define write_lock(_lock) _raw_write_lock(_lock) #define write_unlock(_lock) _raw_write_unlock(_lock) +/* Ensure a lock is quiescent between two critical operations. */ +static inline void spin_barrier(spinlock_t *lock) +{ + spin_lock(lock); + spin_unlock(lock); +} + #define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED #define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED -- 2.30.2